
using System;
using System.Collections.Generic;
using System.Linq;
using MonoMac.Foundation;
using MonoMac.AppKit;
using MonoMac.ObjCRuntime;

namespace SpyTouchClient
{
	public partial class MainWindowController : MonoMac.AppKit.NSWindowController
	{
		Server _server;

		#region Constructors

		// Called when created from unmanaged code
		public MainWindowController (IntPtr handle) : base(handle)
		{
			Initialize ();
		}

		// Called when created directly from a XIB file
		[Export("initWithCoder:")]
		public MainWindowController (NSCoder coder) : base(coder)
		{
			Initialize ();
		}

		// Call to load from the XIB/NIB file
		public MainWindowController () : base("MainWindow")
		{
			Initialize ();
		}

		NSTimer _refreshTimer;

		// Shared initialization code
		void Initialize ()
		{
			_server = new Server (logEntry => { BeginInvokeOnMainThread (delegate { StatusLabel.StringValue = logEntry; }); });
			_refreshTimer = NSTimer.CreateScheduledTimer (2, this, new Selector ("Refresh"), null, true);
		}

		#endregion

		[Export("Refresh")]
		void Refresh ()
		{
			_server.GetVisualTree (views => { BeginInvokeOnMainThread (delegate { SetViews (views); }); });
		}

		public NSOutlineView Views {
			get { return (NSOutlineView)ViewOutlineObject; }
		}
		public NSTextField StatusLabel {
			get { return (NSTextField)StatusLabelObject; }
		}
		public ScreenView Screen {
			get { return (ScreenView)ScreenObject; }
		}

		public override void WindowDidLoad ()
		{
			StatusLabel.StringValue = "Initializing...";
			Views.DataSource = new Data (this);
			Views.Delegate = new Del (this);
			Views.RowHeight = 14;
		}

		class Del : NSOutlineViewDelegate
		{
			MainWindowController _c;

			public Del (MainWindowController c)
			{
				_c = c;
			}
			public override bool ShouldEditTableColumn (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
			{
				return false;
			}
			public override bool ShouldSelectItem (NSOutlineView outlineView, NSObject item)
			{
				_c.Screen.SelectedViewHandle = ((NSNumber)item).Int64Value;
				return true;
			}
		}

		Dictionary<long, ViewBasicInfo> _views = new Dictionary<long, ViewBasicInfo> ();
		Dictionary<long, List<ViewBasicInfo>> _subviews = new Dictionary<long, List<ViewBasicInfo>> ();

		void SetViews (List<ViewBasicInfo> cviews)
		{
			if (cviews.Count == 0) return;
			var views = new Dictionary<long, ViewBasicInfo> ();
			var subviews = new Dictionary<long, List<ViewBasicInfo>> ();
			
			foreach (var v in cviews) {
				ViewBasicInfo vbi = null;
				if (_views.TryGetValue (v.ViewHandle, out vbi)) {
					vbi.Hidden = v.Hidden;
					vbi.Frame = v.Frame;
				} else {
					vbi = v;
				}
				views[v.ViewHandle] = vbi;
				
				var su = vbi.SuperViewHandle;
				List<ViewBasicInfo> subs = null;
				if (!subviews.TryGetValue (su, out subs)) {
					subs = new List<ViewBasicInfo> ();
					subviews[su] = subs;
				}
				subs.Add (vbi);
			}
			
			_views = views;
			_subviews = subviews;

			Screen.Data = _subviews;

			Views.ReloadData ();
		}

		class Data : NSOutlineViewDataSource
		{
			MainWindowController _c;

			public Data (MainWindowController c)
			{
				_c = c;
			}
			public override NSObject GetChild (NSOutlineView outlineView, int index, NSObject item)
			{
				var handle = (item != null) ? ((NSNumber)item).Int64Value : 0L;
				var subs = _c._subviews[handle];
				return subs[index].ViewHandleNumber;
			}
			public override bool ItemExpandable (NSOutlineView outlineView, NSObject item)
			{
				var handle = (item != null) ? ((NSNumber)item).Int64Value : 0L;
				List<ViewBasicInfo> subs = null;
				if (_c._subviews.TryGetValue (handle, out subs)) {
					return subs.Count > 0;
				} else {
					return false;
				}
			}
			public override int CountChildren (NSOutlineView outlineView, NSObject item)
			{
				var handle = (item != null) ? ((NSNumber)item).Int64Value : 0L;
				List<ViewBasicInfo> subs = null;
				if (_c._subviews.TryGetValue (handle, out subs)) {
					return subs.Count;
				} else {
					return 0;
				}
			}
			public override NSObject GetObjectValue (NSOutlineView outlineView, NSTableColumn tableColumn, NSObject item)
			{
				var handle = (item != null) ? ((NSNumber)item).Int64Value : 0L;
				var vbi = _c._views[handle];
				var ident = tableColumn.Identifier.ToString ();
				if (ident == "Type") {
					return new NSString (vbi.TypeName);
				} else if (ident == "Hidden") {
					return new NSString (vbi.Hidden.ToString ());
				} else if (ident == "Frame") {
					return new NSString (vbi.Frame.ToString ());
				} else {
					return new NSString ("");
				}
			}
		}

		//strongly typed window accessor
		public new MainWindow Window {
			get { return (MainWindow)base.Window; }
		}
	}
}

